/*
 ============================================================================
 Name		: NfcConnector.cpp
 Author	  : 
 Version	 : 
 Copyright   : 
 Description : CNfcConnector implementation
 ============================================================================
 */

#include "NfcConnector.h"
#include "P2PMessageSupplier.h"
#include <llcpprovider.h>
#include "LlcpSendHandler.h"
#include "LlcpReceiveHandler.h"
#include "Log.h"
#include <llcpconnorientedtransporter.h>

_LIT8(KApiBridgeNFCService, "APIB");
const TInt KApiBridgeSSAP(35);

CNfcConnector::CNfcConnector(MP2PMessageSupplier* aMessageSupplier) :
	iMessageSupplier(*aMessageSupplier)
	{
	// No implementation required
	}

CNfcConnector::~CNfcConnector()
	{
	Cleanup();
	delete iLlcp;
	iLlcp = 0;
	iNfcServer.Close();
	}

CNfcConnector* CNfcConnector::NewLC(MP2PMessageSupplier* aMessageSupplier)
	{
	CNfcConnector* self = new (ELeave) CNfcConnector(aMessageSupplier);
	CleanupStack::PushL(self);
	self->ConstructL();
	return self;
	}

CNfcConnector* CNfcConnector::NewL(MP2PMessageSupplier* aMessageSupplier)
	{
	CNfcConnector* self = CNfcConnector::NewLC(aMessageSupplier);
	CleanupStack::Pop(); // self;
	return self;
	}

void CNfcConnector::ConstructL()
	{
	User::LeaveIfError( iNfcServer.Open() );
	iLlcp = CLlcpProvider::NewL(iNfcServer);
	}

void CNfcConnector::StartL()
    {
    if ( !iStarted )
        {
		LOG1(_L8("Starting Llcp listening in connection oriented mode."));
        // Adding LLCP link listener
        iLlcp->AddLlcpLinkListenerL( *this );
        
        // Adding listener to service name KApiBridgeNFCService. If any Connection oriented transport 
        // messages are sent to SSAP 35, this listener will handle them.
        iLlcp->StartListeningConnOrientedRequestL( *this, KApiBridgeSSAP );
        
        iStarted = ETrue;
        }
    }

void CNfcConnector::Stop()
    {
    if ( iStarted )
        {
        // Stopping to listen LLCP link
        iLlcp->RemoveLlcpLinkListener();
        
        // Stopping to listen SSAP 35.
        iLlcp->StopListeningConnOrientedRequest( KApiBridgeSSAP );
        iStarted = EFalse;
        
        Cleanup();
        }
    }

void CNfcConnector::LlcpRemoteFound()
	{
    TInt error = KErrNone;
    
    LOG1(_L8("Llcp Remote Found"));
    
    // ASSERT( !iReceiver )
    // ASSERT( !iSender )
	TRAP( error, iSender = CLlcpSendHandler::NewL(
			iLlcp->CreateConnOrientedTransporterL( KApiBridgeSSAP ),
			&iMessageSupplier) )
		
	if ( error == KErrNone )
		{
		iMessageSupplier.ConnectionEstablished();
		}
	else
		{
		Cleanup();
		}
	}

void CNfcConnector::LlcpRemoteLost()
	{
	Cleanup();
	
	iMessageSupplier.ConnectionLost();
    LOG1(_L8("Llcp Remote Lost"));
	}

void CNfcConnector::Cleanup()
	{
	if ( iReceiver )
		{
		iReceiver->Cancel();
		delete iReceiver;
		iReceiver = 0;
		}
	if ( iSender )
		{
		iSender->Cancel();
		delete iSender;
		iSender = 0;
		}
	}

void CNfcConnector::ReadyToSend()
	{
	if (iSender)
		{
		iSender->SendNextMessage();
		}
	}

void CNfcConnector::RemoteConnectRequest( MLlcpConnOrientedTransporter* aConnection )
	{
    TInt error = KErrNone;
    
    // Only accepting one incoming remote connection
    if ( !iReceiver )
        {
        aConnection->AcceptConnectRequest();
        
        // Creating wrapper for connection. 
        TRAP( error, iReceiver = CLlcpReceiveHandler::NewL( aConnection,
        		&iMessageSupplier) );
        if ( error == KErrNone )
            {
            }
        else
            {
            delete aConnection;
            }
        }
    else
        {
        // Decline connection request and delete connection object
        aConnection->DeclineConnectRequest();
        delete aConnection;
        }
	}

